// $Id$
package de.servicezombie.cxf;

import java.io.InputStream;

import javax.ws.rs.ext.ContextResolver;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import de.servicezombie.lang.PrintableInputStreamDecorator;

public class JaxbUnmarshallerFascade {

	private static final Logger log = LoggerFactory.getLogger(JaxbUnmarshallerFascade.class);

	private ContextResolver<JAXBContext> jaxbContextResolver;

	public void setJaxbContextResolver(ContextResolver<JAXBContext> jaxbContextResolver) {
		this.jaxbContextResolver = jaxbContextResolver;
	}

	public <T> T unmarshall(InputStream input, Class<T> type) throws IllegalStateException {
		
		input = PrintableInputStreamDecorator.build(input);		
		if (log.isDebugEnabled()) {
				log.debug("unmarshall: >> '" + input + "', " + type);
		}

		JAXBContext jaxbContext = jaxbContextResolver.getContext(type);
		Assert.notNull(jaxbContext);

		Object object;
		try {
			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
			object = unmarshaller.unmarshal(input);
		}
		catch (JAXBException e) {
			throw new IllegalArgumentException("inputstream data cannot be unmarshalled to " + type, e);
		}

		@SuppressWarnings("unchecked")
		T result = (T) object;

		if (log.isDebugEnabled()) {
			log.debug("unmarshall: << " + result);
		}
		return result;
	}

}
